// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
function pad(str, length = 2) {
    str += "";
    while (str.length < length) {
        str = "0" + str;
    }
    return str.slice(-length);
}

const parser = {
    yyyy: (dateObj) => {
        return pad(dateObj.year, 4);
    },
    yy: (dateObj) => {
        return pad(dateObj.year);
    },
    MM: (dateObj) => {
        return pad(dateObj.month);
    },
    M: (dateObj) => {
        return dateObj.month;
    },
    dd: (dateObj) => {
        return pad(dateObj.day);
    },
    d: (dateObj) => {
        return dateObj.day;
    },
    hh: (dateObj) => {
        return pad(dateObj.hour);
    },
    h: (dateObj) => {
        return dateObj.hour;
    },
    mm: (dateObj) => {
        return pad(dateObj.minute);
    },
    m: (dateObj) => {
        return dateObj.minute;
    },
    ss: (dateObj) => {
        return pad(dateObj.second);
    },
    s: (dateObj) => {
        return dateObj.second;
    },
    SSS: (dateObj) => {
        return pad(dateObj.millisecond, 3);
    },
    S: (dateObj) => {
        return dateObj.millisecond;
    }
};

// 这都n年了iOS依然不认识2020-12-12，需要转换为2020/12/12
function getDate(time) {
    if (time instanceof Date) {
        return time;
    }
    switch (typeof time) {
        case "string": {
            // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
            if (time.indexOf("T") > -1) {
                return new Date(time);
            }
            return new Date(time.replace(/-/g, "/"));
        }
        default:
            return new Date(time);
    }
}

export function formatDate(date, format = "yyyy/MM/dd hh:mm:ss") {
    if (!date && date !== 0) {
        return "";
    }
    date = getDate(date);
    const dateObj = {
        year: date.getFullYear(),
        month: date.getMonth() + 1,
        day: date.getDate(),
        hour: date.getHours(),
        minute: date.getMinutes(),
        second: date.getSeconds(),
        millisecond: date.getMilliseconds()
    };
    const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/;
    let flag = true;
    let result = format;
    while (flag) {
        flag = false;
        result = result.replace(tokenRegExp, function (matched) {
            flag = true;
            return parser[matched](dateObj);
        });
    }
    return result;
}

export function friendlyDate(time, { locale = "zh", threshold = [60000, 3600000], format = "yyyy/MM/dd hh:mm:ss" }) {
    if (time === "-") {
        return time;
    }
    if (!time && time !== 0) {
        return "";
    }
    const localeText = {
        zh: {
            year: "年",
            month: "月",
            day: "天",
            hour: "小时",
            minute: "分钟",
            second: "秒",
            ago: "前",
            later: "后",
            justNow: "刚刚",
            soon: "马上",
            template: "{num}{unit}{suffix}"
        },
        en: {
            year: "year",
            month: "month",
            day: "day",
            hour: "hour",
            minute: "minute",
            second: "second",
            ago: "ago",
            later: "later",
            justNow: "just now",
            soon: "soon",
            template: "{num} {unit} {suffix}"
        }
    };
    const text = localeText[locale] || localeText.zh;
    let date = getDate(time);
    let ms = date.getTime() - Date.now();
    let absMs = Math.abs(ms);
    if (absMs < threshold[0]) {
        return ms < 0 ? text.justNow : text.soon;
    }
    if (absMs >= threshold[1]) {
        return formatDate(date, format);
    }
    let num;
    let unit;
    let suffix = text.later;
    if (ms < 0) {
        suffix = text.ago;
        ms = -ms;
    }
    const seconds = Math.floor(ms / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);
    const days = Math.floor(hours / 24);
    const months = Math.floor(days / 30);
    const years = Math.floor(months / 12);
    switch (true) {
        case years > 0:
            num = years;
            unit = text.year;
            break;
        case months > 0:
            num = months;
            unit = text.month;
            break;
        case days > 0:
            num = days;
            unit = text.day;
            break;
        case hours > 0:
            num = hours;
            unit = text.hour;
            break;
        case minutes > 0:
            num = minutes;
            unit = text.minute;
            break;
        default:
            num = seconds;
            unit = text.second;
            break;
    }

    if (locale === "en") {
        if (num === 1) {
            num = "a";
        } else {
            unit += "s";
        }
    }

    return text.template
        .replace(/{\s*num\s*}/g, num + "")
        .replace(/{\s*unit\s*}/g, unit)
        .replace(/{\s*suffix\s*}/g, suffix);
}
